package edu.nf.vrs.search.service;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import edu.nf.vrs.search.dto.NeedleNumSearchDTO;
import edu.nf.vrs.search.entity.NeedleNum;
import edu.nf.vrs.search.exception.SearchException;
import lombok.extern.log4j.Log4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.UpdateQuery;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/**
 * Author: @Wai
 * Date: 2022-3-29
 */
@DubboService(interfaceClass = NeedleNumSearchService.class, version = "1.0.0")
@Log4j
public class NeedleNumSearchServiceImpl implements NeedleNumSearchService{

    @Autowired
    private ElasticsearchRestTemplate template;

    @PostConstruct
    public void init() {
        if (!template.indexOps(NeedleNum.class).exists()) {
            template.indexOps(NeedleNum.class).create();
            Document doc = template.indexOps(NeedleNum.class).createMapping(NeedleNum.class);
            template.indexOps(NeedleNum.class).putMapping(doc);
            log.info("创建索引成功！");
        }
    }

    @Override
    public List<NeedleNumSearchDTO> search(NeedleNumSearchDTO dto) {
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        ArrayList<NeedleNumSearchDTO> list = new ArrayList<>();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        List<QueryBuilder> queryBuilderList = boolQueryBuilder.filter();
        if(dto.getNeedleNum() == null) dto.setNeedleNum(1);
        if(dto.getInoculateDate() == null) dto.setInoculateDate(DateUtil.today());
        queryBuilderList.add(QueryBuilders.termQuery("status", 0));
        queryBuilderList.add(QueryBuilders.termQuery("needleNum", dto.getNeedleNum()));
        queryBuilderList.add(QueryBuilders.termQuery("inoculateDate", dto.getInoculateDate()));
        if(dto.getVaccineBrand() != null && !"".equals(dto.getVaccineBrand())) {
            queryBuilderList.add(QueryBuilders.termQuery("vaccineBrand", dto.getVaccineBrand()));
        }
        if(dto.getAreaName() != null && !"".equals(dto.getAreaName())) {
            queryBuilderList.add(QueryBuilders.matchQuery("areaName", dto.getAreaName()));
        }
        if(dto.getAddress() != null && !"".equals(dto.getAddress())) {
            queryBuilderList.add(QueryBuilders.multiMatchQuery(dto.getAddress(), "address", "detailed"));
        }
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
        template.search(nativeSearchQueryBuilder.build(),NeedleNumSearchDTO.class,IndexCoordinates.of("needlenum_info"))
                .forEach( hit -> list.add(hit.getContent()));
        return list;
    }

    @Override
    public void add(String json) {
        try {
            List<NeedleNum> needleNums = new ObjectMapper().readValue(json, new TypeReference<List<NeedleNum>>() {});
            for (NeedleNum needleNum : needleNums) {
                System.out.println(needleNum.toString());
                template.save(needleNum);
            }
        } catch (JsonProcessingException e) {
            log.error("添加文档失败",e);
            throw new SearchException(e);
        }

    }

    @Override
    public void update(String json) {
        try {
            List<NeedleNum> needleNums = new ObjectMapper().readValue(json, new TypeReference<List<NeedleNum>>() {});
            ArrayList<UpdateQuery> list = new ArrayList();
            for (NeedleNum needleNum : needleNums) {
                Document doc = Document.create();
                doc.put("areaName", needleNum.getAreaName());
                doc.put("address", needleNum.getAddress());
                doc.put("detailed", needleNum.getDetailed());
                doc.put("tel", needleNum.getTel());
                doc.put("inoculateDate", needleNum.getInoculateDate());
                doc.put("needleNum", needleNum.getNeedleNum());
                doc.put("vaccineBrand", needleNum.getVaccineBrand());
                doc.put("vaccineTotal", needleNum.getVaccineTotal());
                doc.put("vaccineOver", needleNum.getVaccineOver());
                doc.put("status", needleNum.getStatus());
                UpdateQuery updateQuery = UpdateQuery.builder(String.valueOf(needleNum.getNid())).withDocument(doc).build();
                list.add(updateQuery);
            }
            template.bulkUpdate(list, IndexCoordinates.of("needlenum_info"));
        } catch (JsonProcessingException e) {
            log.error("更新文档失败：",e);
            throw new SearchException(e);
        }

    }

    @Override
    public void del(Integer[] ids) {
        try {
            for (Integer id : ids) {
                template.delete(String.valueOf(id), NeedleNum.class);
                log.info("删除文档:" + id);
            }
        } catch (Exception e) {
            log.error("删除文档失败：",e);
            throw new SearchException(e);
        }
    }
}
